// Copyright 2019 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#import "ios/chrome/browser/ui/infobars/presentation/infobar_modal_presentation_controller.h"

#import "ios/chrome/browser/ui/infobars/presentation/infobar_modal_positioner.h"
#import "ios/chrome/browser/ui/util/uikit_ui_util.h"
#import "ios/chrome/common/ui/colors/semantic_color_names.h"

#if !defined(__has_feature) || !__has_feature(objc_arc)
#error "This file requires ARC support."
#endif

namespace {
// The presented view outer margins.
const CGFloat kPresentedViewMargin = 10.0;
// The presented view maximum width.
const CGFloat kPresentedViewMaxWidth = 394.0;
// The rounded corner radius for the container view.
const CGFloat kContainerCornerRadius = 13.0;
}  // namespace

@interface InfobarModalPresentationController ()
// Delegate used to position the ModalInfobar.
@property(nonatomic, weak) id<InfobarModalPositioner> modalPositioner;
@end

@implementation InfobarModalPresentationController

- (instancetype)
    initWithPresentedViewController:(UIViewController*)presentedViewController
           presentingViewController:(UIViewController*)presentingViewController
                    modalPositioner:
                        (id<InfobarModalPositioner>)modalPositioner {
  self = [super initWithPresentedViewController:presentedViewController
                       presentingViewController:presentingViewController];
  if (self) {
    _modalPositioner = modalPositioner;
  }
  return self;
}

- (BOOL)shouldPresentInFullscreen {
  // Don't present in fullscreen when modals are shown using OverlayPresenter
  // so that banners presented are inserted into the correct place in the view
  // hierarchy.  Returning NO adds the container view as a sibling view in front
  // of the presenting view controller's view.
  return NO;
}

- (void)presentationTransitionWillBegin {
  // Add a gesture recognizer to endEditing (thus hiding the keyboard) if a user
  // taps outside the keyboard while one its being presented. Set
  // cancelsTouchesInView to NO so the presented Modal can handle the gesture as
  // well. (e.g. Selecting a row in a TableViewController.)
  UITapGestureRecognizer* tap =
      [[UITapGestureRecognizer alloc] initWithTarget:self.presentedView
                                              action:@selector(endEditing:)];
  tap.cancelsTouchesInView = NO;
  [self.containerView addGestureRecognizer:tap];
}

- (void)containerViewWillLayoutSubviews {
  self.presentedView.frame = [self frameForPresentedView];

  // Style the presented and container views.
  self.presentedView.layer.cornerRadius = kContainerCornerRadius;
  self.presentedView.layer.masksToBounds = YES;
  self.presentedView.clipsToBounds = YES;
  self.containerView.backgroundColor =
      [UIColor colorNamed:kScrimBackgroundColor];

  [super containerViewWillLayoutSubviews];
}

- (CGRect)frameForPresentedView {
  CGRect safeAreaBounds = self.containerView.safeAreaLayoutGuide.layoutFrame;
  CGFloat safeAreaWidth = CGRectGetWidth(safeAreaBounds);
  CGFloat safeAreaHeight = CGRectGetHeight(safeAreaBounds);

  // Calculate the frame width.
  CGFloat maxAvailableWidth = safeAreaWidth - 2 * kPresentedViewMargin;
  CGFloat frameWidth = fmin(maxAvailableWidth, kPresentedViewMaxWidth);

  // Calculate the frame height needed to fit the content.
  CGFloat modalTargetHeight =
      [self.modalPositioner modalHeightForWidth:frameWidth];
  CGFloat maxAvailableHeight = safeAreaHeight - 2 * kPresentedViewMargin;
  CGFloat frameHeight = fmin(maxAvailableHeight, modalTargetHeight);

  // Based on the container width calculate the values in order to center the
  // frame in the X and Y axis.
  CGFloat containerWidth = CGRectGetWidth(self.containerView.bounds);
  CGFloat containerHeight = CGRectGetHeight(self.containerView.bounds);
  CGFloat modalXPosition = (containerWidth / 2) - (frameWidth / 2);
  CGFloat modalYPosition = (containerHeight / 2) - (frameHeight / 2);

  return CGRectMake(modalXPosition, modalYPosition, frameWidth, frameHeight);
}

@end
